#include "lxSession.h"


#define UDP_CMD_PORT    8088
#define UDP_RECIVE_BUFF_MAX_LEN (16*1024)
uint8_t udpSendBuff[UDP_RECIVE_BUFF_MAX_LEN];
static int m_nPort = 0;
static int m_nIp = 0;

static void OnRecvFrom(int sockid, char *data, int len, int ip, int port, void* param)
{
    (void)sockid;(void)param;

    lxSession::Instance().Recvice((uint8_t *)data,len);
    m_nIp = ip;
    m_nPort = port;
}

lxSession::lxSession(void)
{
    ;
}

lxSession::~lxSession(void)
{
    g_Sess.Close();
}

lxSession& lxSession::Instance()
{
	static lxSession _agent;
	return _agent;
}

/**
 * @description: UDP空间发送给用户空间的函数需先注册
 * @param {uint8_t*} data
 * @param {int} len
 * @return {*}
 */
int lxSession::Recvice(uint8_t* data, int len)
{
    if(resolver != nullptr)
    {
        resolver->dataPush(data,len);
        return 0;
    }
    return -1;
}

/**
 * @description: 注册用户空间的解析器函数
 * @param {CallbackCmdFun} callbackFn
 * @return {*}
 */
int lxSession::Register(Resolver<uint8_t> *handle)
{
    if(handle != nullptr)
    {
        resolver = handle;
        return 0;
    }
    return -1;
}

int lxSession::sendto(struct cmdDataType* cmd,uint8_t * cmdData)
{
    static struct dataType sendStruct;
    size_t sendLen = 0;
    if (cmd == nullptr) {
        return -1;
    }
    if ((cmd->dataLen > 0) && (cmdData == nullptr)) {
        return -2;
    }
    if (cmd->dataLen < 0) {
        return -3;
    }
    if ( cmd->dataLen > sizeof(udpSendBuff) ) {
        qlog_e("lxSession udp databuf too short:%d",cmd->dataLen);
        return -4;
    }

    memset(&sendStruct,0,sizeof(dataType));

    sendStruct.head = 0x5555aaaa;
    sendStruct.tail = 0xaaaa5555;
    sendStruct.cmdType = cmd->cmdType;
    sendStruct.cmdChildType = cmd->cmdChildType;
    sendStruct.dataLen = cmd->dataLen;

    if(sendStruct.dataLen > 0){
        sendStruct.followData = 1;
        memcpy(udpSendBuff + sizeof(struct dataType),cmdData,cmd->dataLen);
    } else {
        sendStruct.followData = 0;
    }
    
    memcpy(udpSendBuff,&sendStruct,sizeof(struct dataType));
    sendLen = sizeof(struct dataType) + cmd->dataLen;

    if  (m_nIp == 0 || m_nPort == 0) {
        m_nIp = inet_addr(m_nCmdIp);
        m_nPort = UDP_CMD_PORT;
    }
    return g_Sess.Send((char *)udpSendBuff, sendLen, m_nIp, m_nPort);
}

int lxSession::sendto(uint8_t* data,size_t len)
{
    size_t sendLen = len;
    if ((len > 0) && (data == nullptr)) {
        return -1;
    }
    if (len < 0) {
        return -2;
    }
    if ( len > sizeof(udpSendBuff) ) {
        qlog_e("lxSession udp databuf too short:%d",len);
        return -3;
    }
    memcpy(udpSendBuff,data,sendLen);

    if  (m_nIp == 0 || m_nPort == 0) {
        m_nIp = inet_addr(m_nCmdIp);
        m_nPort = UDP_CMD_PORT;
    }

    return g_Sess.Send((char *)udpSendBuff, sendLen, m_nIp, m_nPort);
}

int lxSession::Init(const char* nLocalIp, int nPort)
{	 
    m_nPort = nPort;
    qlog_n("Lx UdpServer ip:%s port:%d",nLocalIp,nPort);
    char *prctl = (char*)"lxUdpServer";
	if (g_Sess.Open(nLocalIp,nPort, OnRecvFrom, (void *)prctl) < 0)
	{
		qlog_e("Lx UdpServer open error");
		return -1;
	}
    qlog_i("Lx UdpServer initialized ...");
	// g_Sess.m_pTimeOutCB = OnTimeOut;
	return 0;
}